<?php
/**
 * PartCategoryRepo.php
 *
 * @copyright   2023 thingsworld.com.cn - All Rights Reserved
 * @link        http://thingsworld.com.cn/
 * @author      stiffer.chen <chenl@thingsworld.com.cn>
 * @created     2023-05-12 16:56:57
 * @modified    2023-05-12 16:56:57
 *
 */

namespace App\Repositories;

use App\Models\DictModel;
use App\Models\Inventory;
use App\Models\PartCategory;
use App\Models\UserInventory;
use App\Models\UserModel;
use App\Models\Warehouse;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class PartCategoryRepo
{
    public static function getList()
    {
        $perPage = (int)request('limit');
        if ($perPage < 1) {
            $perPage = 10;
        }
        $keyword = trim(request('keyword', ''));

        $builder = PartCategory::query()
            ->orderByDesc('update_time')
            ->orderByDesc('create_time');
        if ($keyword) {
            $builder->where(function ($query) use ($keyword) {
                $query->where('name', 'like', "%{$keyword}%")
                    ->orWhere('c_number', 'like', "%{$keyword}%")
                    ->orWhere('type', 'like', "%{$keyword}%")
                    ->orWhere('model', 'like', "%{$keyword}%");
            });
        }
        $results = $builder->paginate($perPage);
        $results->transform(function ($item) {
            return self::getDetail($item);
        });
        return $results;
    }

    // 启用备件分类
    public static function active($id)
    {
        return self::setStatus($id, 1);
    }

    public static function inactive($id)
    {
        return self::setStatus($id, 0);
    }

    private static function setStatus($id, $status)
    {
        $partCategory = PartCategory::find($id);
        if (empty($partCategory)) {
            throw new \Exception('配件品类不存在');
        }
        $partCategory->status = $status;
        $partCategory->saveOrFail();
        return self::fetch($partCategory->id);
    }

    public static function params()
    {
        $typeCode = 'part-type';
        $uomCode = 'part-uom';
        $code = [$typeCode, $uomCode];

        $builder = DictModel::query()
            ->from('dict as d')
            ->join('dict_data as dd', 'dd.dict_id', '=', 'd.id')
            ->select(['dd.name', 'd.code'])
            ->whereIn('d.code', $code);
        $params = $builder->get();
        $types = $uoms = [];

        foreach ($params as $param) {
            $code = $param->code;
            if ($code == $typeCode) {
                $types[] = $param->name;
            }
            if ($code == $uomCode) {
                $uoms[] = $param->name;
            }
        }

        return [
            'type' => $types,
            'uom' => $uoms
        ];
    }

    public static function store($id)
    {
        $requestData = self::requestData($id);
        if ($id) {
            $partCategory = PartCategory::find($id);
        } else {
            $partCategory = new PartCategory();
        }
        if (empty($partCategory)) {
            $partCategory = new PartCategory();
        }
        $partCategory->fill($requestData);
        $partCategory->saveOrFail();
        return self::fetch($partCategory->id);
    }

    public static function fetch($id)
    {
        $partCategory = PartCategory::find($id);
        $partCategory->with(['user']);
        if (empty($partCategory)) {
            throw new \Exception('品类不存在');
        }
        return self::getDetail($partCategory);
    }

    public static function destroy($id)
    {
        $partCategory = PartCategory::find($id);
        if (empty($partCategory)) {
            throw new \Exception('品类不存在');
        }
        // @todo 有没有库存信息，有没有使用记录
        $inventroyCount = $partCategory->inventories->count();
        if ($inventroyCount > 0) {
            throw new \Exception("删除失败， 有 {$inventroyCount} 个库存正在使用该品类");
        }
        $userInventoryCount = $partCategory->user_inventories->count();
        if ($userInventoryCount > 0) {
            throw new \Exception("删除失败， 有 {$inventroyCount} 个个人仓库正在使用该品类");
        }
        $partCategory->delete();
    }

    private static function getDetail($partCategory)
    {
        $partCategoryArr = $partCategory->toArray();
        $partCategoryArr['create_user_name'] = $partCategory->user->realname ?? '';
        $partCategoryArr['create_time'] = Carbon::parse($partCategoryArr['create_time'])->toDateTimeString();
        $partCategoryArr['update_time'] = Carbon::parse($partCategoryArr['update_time'])->toDateTimeString();

        // 使用记录
        $partCategoryArr['use_detail'] = [];
        $partCategoryArr['inventory_detail'] = self::inventoryDetail($partCategory);

        return $partCategoryArr;
    }

    private static function inventoryDetail($partCategory)
    {
        $cid = $partCategory->id;
        $inventoriesBuilder = Inventory::query()
            ->select(['w.id', DB::raw('sum(' . DB::connection()->getTablePrefix() . 'i.`inventory`) as total')])
            ->from('inventory as i')
            ->join('warehouse as w', 'w.id', '=', 'i.warehouse_id')
            ->where('c_id', $cid)
            ->groupBy('w.id');
        $inventories = $inventoriesBuilder->get()->keyBy('id')->toArray();
        $wIds = array_keys($inventories);

        $ws = Warehouse::query()->whereIn('id', $wIds)->select(['id', 'name'])->get()->keyBy('id')->toArray();

        $is = [];
        foreach ($inventories as $wId => $item) {
            $is[] = [
                'name' => $ws[$wId]['name'] ?? '',
                'type' => "备件库",
                'total' => $item['total'] ?? ''
            ];
        }

        $uiBuilder = UserInventory::query()
            ->select(['i.user_id', DB::raw('sum(' . DB::connection()->getTablePrefix() . 'i.`inventory`) as total')])
            ->from('user_inventory as i')
            ->where('c_id', $cid)
            ->groupBy('i.user_id');
        $uis = $uiBuilder->get()->keyBy('user_id')->toArray();
        $uIds = array_keys($uis);
        $users = UserModel::query()->select(['realname'])->whereIn('id', $uIds)->get()->keyBy('id')->toArray();
        foreach ($uis as $userId => $item) {
            $itemUser = UserModel::find($userId);
            $userName = $itemUser->realname ?? '';
            $is[] = [
                'name' => $userName,
                'type' => "个人库",
                'total' => $item['total'] ?? ''
            ];
        }
        return $is;
    }

    private static function requestData($id)
    {
        $data = request()->getContent();
        $arr = json_decode($data, true);


        $cNumber = trim($arr['c_number'] ?? '');
        if (!$cNumber) {
            throw new \Exception('请输入编码');
        }

        $numberCategory = PartCategory::byNumber($cNumber)->first();
        if (!$id && !empty($numberCategory)) {
            throw new \Exception('该编码已被使用');
        }
        if ($id && $numberCategory->id != $id) {
            throw new \Exception('该编码已被使用');
        }

        $name = trim($arr['name'] ?? '');
        if (!$name) {
            throw new \Exception('请输入名称');
        }
        $nameCategory = PartCategory::byName($name)->first();
        if (!$id && !empty($nameCategory)) {
            throw new \Exception('该名称已被使用');
        }
        if ($id && $nameCategory->id != $id) {
            throw new \Exception('该名称已被使用');
        }

        $params = self::params();
        $types = $params['type'] ?? [];
        $uoms = $params['uom'] ?? [];

        $type = trim($arr['type'] ?? '');
        if (!$type) {
            throw new \Exception('请选择类别');
        }
        if (!in_array($type, $types)) {
            throw new \Exception('类别错误');
        }

        $model = trim($arr['model'] ?? '');

        $uom = trim($arr['uom'] ?? '');
        if (!$uom) {
            throw new \Exception('请选择计量单位');
        }
        if (!in_array($uom, $uoms)) {
            throw new \Exception('计量单位错误');
        }

        $salePrice = floatval($arr['sale_price'] ?? '');
        $outPrice = floatval($arr['out_price'] ?? '');

        $description = $arr['description'] ?? '';
        $createUserId = registry('user_id') ?? 0;
        $status = intval($arr['status'] ?? 1);
        if (!in_array($status, [0, 1])) {
            $status = 1;
        }

        return [
            'name' => $name,
            'c_number' => $cNumber,
            'type' => $type,
            'model' => $model,
            'uom' => $uom,
            'sale_price' => $salePrice,
            'out_price' => $outPrice,
            'description' => $description,
            'status' => $status,
            'create_user_id' => $createUserId
        ];
    }
}